using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Sustainalytics.DataLayer.ConnectionStrings;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ConnectionStrings;
using Sustainalytics.Entities.Governance;
using Sustainalytics.Governance.Service.Dto;
using Sustainalytics.Utils;
using System.Web.Http.Cors;

namespace Sustainalytics.Governance.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/company")]
    public class GovernanceCompanyRelativePerformanceController : ApiController
    {
        private readonly IRepositoryCollection<GovernanceComputationResult> _repositoryCompResult;
        private readonly IRepositoryCollection<GovernanceIssue> _repositoryIssues;
        private readonly IRepositoryCollection<GovernanceCompanyProfile> _repositoryCompanyProfile;
        private readonly IRepositoryCollection<GovernanceAssessmentThreshold> _governanceAssesmentThreshold;

        public GovernanceCompanyRelativePerformanceController()
        {
            var connectionStringsManager =
                ConnectionStringsManager.GetInstance(
                    ConnectionStringsRepository.GetInstance(ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString));
            _repositoryCompResult =
                new RepositoryCollection<GovernanceComputationResult>(
                    connectionStringsManager.GetConnectionString(ConnectionStringType.GovernanceDW));
            _repositoryCompanyProfile = new RepositoryCollection<GovernanceCompanyProfile>(
                    connectionStringsManager.GetConnectionString(ConnectionStringType.GovernanceDW));
            _repositoryIssues = new RepositoryCollection<GovernanceIssue>(connectionStringsManager.GetConnectionString(ConnectionStringType.GovernanceDW));
            _governanceAssesmentThreshold = new RepositoryCollection<GovernanceAssessmentThreshold>(connectionStringsManager.GetConnectionString(ConnectionStringType.GovernanceDW));
        }


        [Route("{companyId}/relativePerformance")]
        public HttpResponseMessage Get([FromUri] Guid companyId, [FromUri] bool details, [FromUri] bool excludeOverallScore = false)
        {
            try
            {

                if (details)
                {
                    return Request.CreateResponse(HttpStatusCode.OK, GetRelativePerformanceAnalysis(companyId, excludeOverallScore));
                }
                var companyFound =
                    _repositoryCompResult.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();
                var companyProfile =
                    _repositoryCompanyProfile.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();
                var govdto = new GovernanceRelativePerformanceDto()
                {
                    CompanyId = companyId,
                    Peers =
                        companyFound.RelativePerformance.PeersList.OrderBy(a => a.Rank).Select(a => new CompanyDataDto()
                        {
                            CompanyId = a.CompanyId,
                            CompanyName = a.CompanyName,
                            Score = Convert.ToInt32(a.Score)
                        }).ToArray(),
                    TopFive =
                        companyFound.RelativePerformance.Top5List.OrderBy(a => a.Rank).Select(a => new CompanyDataDto()
                        {

                            CompanyId = a.CompanyId,
                            CompanyName = a.CompanyName,
                            Score = Convert.ToInt32(a.Score)
                        }).ToArray(),
                    MarketCapRangeFrom = companyFound.RelativePerformance.MarketCapRangeFrom / 1000,
                    MarketCapRangeTo = companyFound.RelativePerformance.MarketCapRangeTo / 1000
                };
                govdto.Region = companyProfile.RegionName;

                var regionPerformance = companyFound.OverallPerformance.Performances
                    .Where(a => a.PerformanceType == PerformanceType.Region).ToList();

                if (regionPerformance.Count == 1)
                {
                    govdto.Percentile = ScoreConversion.GetRoundedScore(regionPerformance[0].Percentile);
                }

                return Request.CreateResponse(HttpStatusCode.OK, govdto);
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An uhandled exception happened");
            }
        }

        [Route("{companyId}/summaryBenchmark")]
        public IHttpActionResult Get()
        {
            var summaryThreshold = _governanceAssesmentThreshold.ReadAllWhere(a => a.Number == "CG.0");
            return Ok(summaryThreshold);
        }


        [Route("{companyId}/overallPerformance")]
        public HttpResponseMessage Get([FromUri] Guid companyId)
        {
            try
            {
                var dto = new GovernanceCompanyOverallDto() { CompanyId = companyId };
                var computationResult = _repositoryCompResult.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();
                var profile = _repositoryCompanyProfile.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();

                if (computationResult != null && profile != null)
                {
                    dto.AnalystView = profile.AnalystView;
                    dto.Score = Convert.ToInt32(computationResult.OverallPerformance?.Score);
                    dto.Assesment = computationResult.OverallPerformance != null ? (int)computationResult.OverallPerformance.Assessment + 1 : 1;
                    if (profile.Outlook.HasValue)
                    {
                        dto.Outlook = (int?)profile.Outlook;
                    }
                    dto.Region = profile.RegionName;

                    var regionPerformance = computationResult.OverallPerformance?.Performances
                        .Where(a => a.PerformanceType == PerformanceType.Region).ToList();
                    if (regionPerformance != null && regionPerformance.Count == 1)
                    {
                        dto.RegionalPercentile = ScoreConversion.GetRoundedScore(regionPerformance[0].Percentile);
                    }
                }
                else
                    dto = null;

                return Request.CreateResponse(HttpStatusCode.OK, dto);
            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "An unhandled exception happened");
            }
        }

        private GovernanceRelativePerformanceDetailsDto GetRelativePerformanceAnalysis(Guid companyId, bool excludeOverallScore)
        {
            var computationResult = _repositoryCompResult.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();
            var companyProfile = _repositoryCompanyProfile.ReadAllWhere(a => a.Id == companyId, skip: 0, take: 1).FirstOrDefault();

            var dto = new GovernanceRelativePerformanceDetailsDto
            {
                CompanyId = companyId,
                Region = (companyProfile != null) ? companyProfile.RegionName : null,
                Industry = (companyProfile != null) ? companyProfile.Industry : null
            };

            if (computationResult == null) return dto;

            if (computationResult.OverallPerformance != null)
            {
                var region = computationResult.OverallPerformance.Performances.Where(a => a.PerformanceType == PerformanceType.Region).ToList();

                if (region.Count == 1)
                {
                    dto.NoOfRegionCompanies = region[0].GroupCount.ToString();

                    var industry = computationResult.OverallPerformance.Performances.Where(a => a.PerformanceType == PerformanceType.PeerGroup).ToList();
                    dto.NoOfIndustryCompanies = industry[0].GroupCount.ToString();
                }
            }

            var issues = new List<IssuesRelativePerformanceDto>();
            if (excludeOverallScore == false)
            {
                issues.Add(new IssuesRelativePerformanceDto()
                {
                    CompanyId = companyId,
                    Name = "Overall Score",
                    Score = ScoreConversion.GetRoundedScore(computationResult.OverallPerformance.Score),
                    IndustryPercentile = ScoreConversion.GetRoundedScore(
                        (computationResult.OverallPerformance.Performances.FirstOrDefault(a => a.PerformanceType == PerformanceType.PeerGroup) ?? new GovernancePerformance()).Percentile).ToString(),
                    RegionPercentile = ScoreConversion.GetRoundedScore(
                        (computationResult.OverallPerformance.Performances.FirstOrDefault(a => a.PerformanceType == PerformanceType.Region) ?? new GovernancePerformance()).Percentile).ToString(),
                    AssesmentType = (int)computationResult.OverallPerformance.Assessment + 1,
                    Number = "CG.0"
                });
            }

            issues.AddRange(computationResult.IssuesPerformance.Select(x => new IssuesRelativePerformanceDto
            {
                CompanyId = companyId,
                Name = x.Name,
                Score = ScoreConversion.GetRoundedScore(x.Score),
                IndustryPercentile = ScoreConversion.GetRoundedScore(
                    (x.Performances.FirstOrDefault(a => a.PerformanceType == PerformanceType.PeerGroup) ?? new GovernancePerformance()).Percentile).ToString(),
                RegionPercentile = ScoreConversion.GetRoundedScore(
                    (x.Performances.FirstOrDefault(a => a.PerformanceType == PerformanceType.Region) ?? new GovernancePerformance()).Percentile).ToString(),
                AssesmentType = (int) x.Assessment + 1,
                Number = x.Number
            }));

            dto.Issues = issues.ToArray();

            return dto;
        }



        [Route("{companyId}/cgissues/{issueid}/indicators/scoresandasseement")]
        public HttpResponseMessage Get([FromUri] Guid companyId, [FromUri] string issueId)
        {
            try
            {
                var found = _repositoryIssues.ReadAllWhere(a => a.CompanyId == companyId && a.Number == issueId, skip: 0,
                    take: 1).FirstOrDefault();
                var indicators = found.Indicators.OrderBy(i => Convert.ToInt32(i.Number.Substring(5))).ToList().Select(a => new IndicatorDataIssue()
                {
                    CompanyId = companyId,
                    Id = a.Id,
                    Name = a.Name,
                    Number = a.Number,
                    IssueName = found.Name,
                    Score = a.Score,
                    StandardText = a.Description,
                    Comment = a.Comment,
                    TickBoxes = a.Tickedboxes.Select(d => d.Value).ToList(),
                    Outlook = a.Outlook
                }).ToList();
                return Request.CreateResponse(HttpStatusCode.OK, indicators);

            }
            catch (Exception ex)
            {
                GovernanceEventSource.Log.LogError(ex);
                return Request.CreateResponse(HttpStatusCode.InternalServerError, "An unhandled exception");
            }
        }
    }
}